package org.example.service.impl;

import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.fasterxml.jackson.databind.ObjectMapper;
import lombok.RequiredArgsConstructor;
import lombok.SneakyThrows;
import org.example.entity.*;
import org.example.exception.LoginException;
import org.example.service.IMenuService;
import org.example.service.IRoleService;
import org.example.service.IUserService;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import java.time.Duration;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import java.util.UUID;
import java.util.stream.Collectors;

@Service
@RequiredArgsConstructor
public class TokenService {
    private final IUserService userService;
    private final IRoleService roleService;
    private final IMenuService menuService;
    private final StringRedisTemplate stringRedisTemplate;

    private static final String LOGIN_KEY="di8:rbac:login:";
    /*
    * 1.根据登录名查询用户
    * 2.比对密码
    * 3.比对状态
    * 4.获取用户的角色列表
    * 5.根据角色获取用户权限
    * 6.创建(生成)Token,存储用户及角色,权限到redis
    * */
    @SneakyThrows
    public Token createToken(LoginVO loginVO){
        //1.
        User user=userService.getOne(Wrappers.lambdaQuery(User.class).eq(User::getUserName,loginVO.getLoginName()));
        if (user==null) throw new LoginException("用户不存在");
        if (!user.getPassword().equals(loginVO.getPassword()))throw new LoginException("密码不正确");
        if (!user.getStatus().equals("0")) throw new LoginException("用户未激活");
        //2.获取用户所有的角色列表
        List<Role> roleList=roleService.listByUserId(user.getUserId());
        Long[] roleIds=roleList.stream().mapToLong(Role::getRoleId).boxed().toArray(Long[]::new);
        //3.根据角色获取所有菜单
        List<Menu> menuList=menuService.listByRoleIds(roleList.stream().mapToLong(Role::getRoleId).boxed().toArray(Long[]::new));
        //4.存储到redis
        String uuid= UUID.randomUUID().toString();
        Set<String> roleNames=roleList.stream().map(Role::getRoleKey).collect(Collectors.toSet());
        Set<String> perms=menuList.stream()
                .filter(menu -> StringUtils.hasText(menu.getPerms()))
                .map(Menu::getPerms).collect(Collectors.toSet());

        LoginUser loginUser=new LoginUser(roleNames,perms,user);
        String json=new ObjectMapper().writeValueAsString(loginUser);
        stringRedisTemplate.opsForValue().set(LOGIN_KEY+uuid,json, Duration.ofMillis(30));
        return new Token(System.currentTimeMillis(),System.currentTimeMillis()+1800000,uuid,user.getNickName());
    }

    public void removeToken(String token) {
        stringRedisTemplate.delete(LOGIN_KEY+token);
    }
    @SneakyThrows
    public boolean hasPerms(String perms) {
        //判断请求头有没有token权限
        ServletRequestAttributes requestAttributes =(ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
        String token=requestAttributes.getRequest().getHeader("token");
        if (StringUtils.isEmpty(token))return false;
//判断redis找的到吗
         String json =stringRedisTemplate.opsForValue().get(LOGIN_KEY+token);
         if (StringUtils.isEmpty(json))return false;
//判断你是否有权限
         LoginUser loginUser=new ObjectMapper().readValue(json, LoginUser.class);
         Set<String> permsAndRoles=new HashSet<>();
         permsAndRoles.addAll(loginUser.getPerms());
         permsAndRoles.addAll(loginUser.getRoleName());

         return permsAndRoles.contains(perms);
    }
}
